home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnulib / libsrc98.zoo / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-10  |  5.7 KB  |  241 lines

  1. #include <stddef.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <osbind.h>
  5. #include <memory.h>
  6. #include <time.h>
  7. #include <fcntl.h>
  8. #include <string.h>
  9. #include "symdir.h"
  10. #include <unistd.h>
  11. #include "lib.h"
  12. #include <ctype.h>
  13.  
  14. int    errno;
  15. int    __mint;        /* 0 for TOS, MiNT version number otherwise */
  16. int    _console_dev;
  17.  
  18. FILE    _iob[_NFILE];    /* stream buffers initialized below */
  19.  
  20. /* functions registered by user for calling at exit */
  21. #ifdef __STDC__
  22. typedef void (*ExitFn)(void);
  23. #else
  24. typedef void (*ExitFn)();
  25. #endif
  26. static ExitFn *_at_exit;
  27. static int num_at_exit;    /* number of functions registered - 1 */
  28. extern clock_t    _start_time;    /* defined in clock.c */
  29. extern clock_t    _child_runtime;    /* defined in spawnve.c */
  30. extern clock_t    _sys_runtime;    /* defined in spawnve.c */
  31.  
  32. /*
  33.  * get MiNT version number
  34.  */
  35. static void
  36. getMiNT(void)
  37. {
  38.     long *cookie;
  39.  
  40.     cookie = *((long **) 0x5a0L);
  41.     if (!cookie)
  42.         __mint = 0;
  43.     else {
  44.         while (*cookie) {
  45.             if (*cookie == 0x4d694e54L) {
  46.                 __mint = cookie[1];
  47.                 return;
  48.             }
  49.             cookie += 2;
  50.         }
  51.     }
  52.     __mint = 0;
  53. }
  54.  
  55. /* supplied by the user */
  56. __EXTERN int main __PROTO((int, char **, char **));
  57.  
  58. /* in getbuf.c */
  59. __EXTERN void _getbuf __PROTO((FILE *));
  60.  
  61. #if __GNUC__ > 1
  62. /* in libgcc2.c */
  63. __EXTERN void __do_global_dtors __PROTO ((void));
  64. #endif
  65.  
  66. void
  67. _main(_argc, _argv, _envp)
  68.     long _argc;
  69.     char **_argv, **_envp;
  70. {
  71.     char *tty;
  72.     register FILE *f;
  73.     register int i;
  74.      char *s, *t;
  75.     extern int __default_mode__; /* in defmode.c or defined by user */
  76.     int main(int, char **, char **);
  77.  
  78.     /* clear isatty status for dumped programs */
  79.     for (i = 0; i < __NHANDLES; i++)
  80.       __open_stat[i].status = FH_UNKNOWN;
  81.     _start_time = 0;    /* for dumped prgs */
  82.  
  83.     _start_time = clock();
  84.     _child_runtime = _sys_runtime = 0;
  85.     num_at_exit = 0;
  86. /*
  87.  * check for MiNT
  88.  */
  89.      (void)Supexec(getMiNT);
  90.  
  91. /*
  92.  * check environment for various things
  93.  */
  94.     _set_unixmode(getenv("UNIXMODE"));
  95.  
  96.     if (tty = getenv("TTY")) {
  97.         if (!strcmp(tty, "AUX:") || !strcmp(tty, "aux:"))
  98.             _console_dev = 1;
  99.         else
  100.             _console_dev = 2;
  101.     }
  102.     else
  103.         _console_dev = 2;
  104.  
  105. /* if stderr is not re-directed to a file, force 2 to console
  106.  * (UNLESS we've been run from a shell we trust, i.e. one that supports
  107.  *  the official ARGV scheme, in which case we leave stderr be).
  108.  */
  109.     if(!*_argv[0] && isatty(2))
  110.         (void)Fforce(2, _console_dev - 3);
  111.  
  112.     stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
  113.     stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
  114.     stderr->_flag = _IORW|_IONBF|__default_mode__;
  115.              /* some brain-dead people read from stderr */
  116.  
  117.     for(i = 0, f = _iob; i < 3; ++i, ++f) {    /* flag device streams */
  118.         if(isatty(f->_file = i))
  119.             f->_flag |= _IODEV;
  120.         else
  121.             if(f == stdout)    { /* stderr is NEVER buffered */
  122.             /* if stdout re-directed, make it full buffered */
  123.                 f->_flag &= ~(_IOLBF | _IONBF);
  124.                 f->_flag |=  _IOFBF;
  125.             }
  126.         _getbuf(f);    /* get a buffer */
  127.     }
  128.  
  129.     for(i = 0; i <= 2; i++) {
  130.         __open_stat[__OPEN_INDEX(i)].filename = isatty(i) ? 
  131.             ((_console_dev == 2) ? "/dev/console" : "/dev/tty1")
  132.                 : (char *)NULL; /* if it was re-dir */
  133.     }
  134.  
  135.      for(i = 3; i < _NFILE; i++, f++) {
  136.       f->_flag = 0;        /* clear flags, if this is a dumped program */
  137.     }
  138.  
  139.     /* Fix up environment, if necessary. At present, the only variable
  140.      * affected is PATH; the "standard" path separators for PATH are
  141.      * ',' and ';' in the Atari world, but POSIX mandates ':'. This
  142.      * conflicts with the use of ':' as a drive separator, so we
  143.      * also convert names like A:\foo to /dev/A/foo
  144.      * NOTE: this conversion must be undone in spawn.c so that
  145.      * old fashioned programs will understand us!
  146.      */
  147.     for (i = 0; s = _envp[i]; i++) {    /* '=', NOT '==' */
  148.         if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
  149.             s[3] == 'H' && s[4] == '=') {
  150.             _envp[i] = (char *)malloc(4 * strlen(s));
  151.             strncpy(_envp[i], s, 5);
  152.             t = _envp[i]+5;
  153.             s += 5;
  154.             while (*s) {
  155.                 if (s[1] == ':' && isalpha(*s)) {    /* drive letter */
  156.                     *t++ = '/';
  157.                     *t++ = 'd'; *t++ = 'e'; *t++ = 'v';
  158.                     *t++ = '/'; *t++ = *s++; s++;
  159.                 } else if (*s == ';' || *s == ',') {
  160.                     *t++ = ':'; s++;
  161.                 } else {
  162.                     *t++ = *s++;
  163.                 }
  164.             }
  165.             *t++ = 0;
  166.             break;
  167.         }
  168.     }
  169.  
  170.     errno = 0;
  171.  
  172.     /* ANSI-Draft: A return from the initial call to the main      */
  173.     /* function is equivalent to calling the exit function with    */
  174.     /* the value returned by the main function as its argument. If */
  175.     /* the main function executes a return that specifies no       */
  176.     /* value, the termination status returned to the host            */
  177.     /* environment is undefined. [section 2.1.2.2]               */
  178.     exit(main((int) _argc, _argv, _envp));    /* if main() returns exit */
  179. }
  180.  
  181. __EXITING _exit(status)
  182.     int status;
  183. {
  184.     __exit((long)status);
  185. }
  186.  
  187. /* For debuggers: non-macro versions of std{in,out,err}. */
  188. #undef stdin
  189. #undef stdout
  190. #undef stderr
  191. FILE *stdin = &_iob[0];
  192. FILE *stdout = &_iob[1];
  193. FILE *stderr = &_iob[2];
  194.  
  195. __EXITING exit(status)
  196.     int status;
  197. {
  198.     register int i, f;
  199.  
  200.  
  201. #if __GNUC__ > 1
  202.     __do_global_dtors ();
  203. #endif
  204.  
  205.     for(i=0; i<_NFILE; ++i) {
  206.         f = _iob[i]._flag;
  207.         if(f & (_IORW | _IOREAD | _IOWRT))
  208.             if (_iob[i]._file <= 2) /* only flush std. streams */
  209.                 fflush(&_iob[i]);
  210.             else
  211.                 fclose(&_iob[i]);
  212.     }
  213.  
  214.     for(i = num_at_exit - 1; i >= 0; --i)
  215.         (*_at_exit[i])();
  216.  
  217.     _exit(status);
  218. }
  219.  
  220. /* register a function for execution on termination */
  221. /* Ansi requires atleast 32 entries, we make it dynamic and hope
  222.    it meets the ansi requirement */
  223.  
  224. int atexit(func)
  225.     ExitFn func;
  226. {
  227.         ExitFn *new_at_exit = _at_exit;
  228.     
  229.     if (num_at_exit == 0)
  230.         new_at_exit = (ExitFn *)malloc((size_t)sizeof(ExitFn));
  231.     else
  232.         new_at_exit = (ExitFn *)realloc(new_at_exit,
  233.             (size_t)((num_at_exit + 1) * sizeof(ExitFn)));
  234.     if(new_at_exit == (ExitFn *)NULL)
  235.         return -1;    /* failure */
  236.  
  237.         _at_exit = new_at_exit;
  238.     _at_exit[num_at_exit++] = func;
  239.     return 0;        /* success */
  240. }
  241.